<!doctype html>
<html>

<head>
  <meta charset="utf-8" />
  <title>Basic Draw Point</title>
  <script id="shader-vs" type="x-shader/x-vertex">
    attribute vec2 aPos;
    uniform vec2 u_resolution;
    void main(void){
      // 从像素坐标转换到 0.0 到 1.0
      vec2 zeroToOne = aPos / u_resolution;
      // 再把 0->1 转换 0->2
      vec2 zeroToTwo = zeroToOne * 2.0;
      // 把 0->2 转换到 -1->+1 (裁剪空间)
      vec2 clipSpace = zeroToTwo - 1.0;

      gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
      gl_PointSize = 20.0;
    }
  </script>
  <script id="shader-fs" type="x-shader/x-fragment">
    void main(void) {
      gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
  </script>
</head>

<body>
  <canvas id="canvas" width="400" height="400"></canvas>
  <script>
    var gl
    var canvas = document.getElementById('canvas')
    var glProgram = null

    function getGLContext() {
      var glContextNames = ['webgl', 'experimental-webgl']
      for (var i = 0; i < glContextNames.length; i++) {
        try {
          gl = canvas.getContext(glContextNames[i])
        } catch (e) {}
        if (gl) {
          gl.clearColor(74 / 255, 115 / 255, 94 / 255, 1.0)
          gl.clear(gl.COLOR_BUFFER_BIT)
          gl.viewport(0, 0, canvas.width, canvas.height)
          break
        }
      }
    }
    
    // 编译shaders
    function initShaders() {
      // get shader source
      var vs_source = document.getElementById('shader-vs').innerHTML,
        fs_source = document.getElementById('shader-fs').innerHTML

      // compile shaders	
      let vertexShader = makeShader(vs_source, gl.VERTEX_SHADER) // 顶点着色器 针对每个顶点执行
      let fragmentShader = makeShader(fs_source, gl.FRAGMENT_SHADER) // 片段着色器 负责计算输出到屏幕的像素颜色

      // create program
      glProgram = gl.createProgram();

      // attach and link shaders to the program
      gl.attachShader(glProgram, vertexShader);
      gl.attachShader(glProgram, fragmentShader);
      gl.linkProgram(glProgram);

      if (!gl.getProgramParameter(glProgram, gl.LINK_STATUS)) {
        alert("Unable to initialize the shader program.");
      }

      //use program
      gl.useProgram(glProgram);
    }

    function makeShader(src, type) {
      //compile the vertex shader
      var shader = gl.createShader(type);
      gl.shaderSource(shader, src);
      gl.compileShader(shader);

      if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert("Error compiling shader: " + gl.getShaderInfoLog(shader));
      }
      return shader;
    }
    
    // 设置buffer
    function setupBuffer() {
      var vertex = [ 200, 200 ];
      var vertexBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertex), gl.STATIC_DRAW);

      var aVertexPosition = gl.getAttribLocation(glProgram, 'aPos');
      var resolutionUniformLocation = gl.getUniformLocation(glProgram, "u_resolution");
      gl.vertexAttribPointer(aVertexPosition, 2, gl.FLOAT, false, 0, 0);
      // 设置全局变量 分辨率
      gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height);
      gl.enableVertexAttribArray(aVertexPosition);
    }

    function draw() {
      gl.drawArrays(gl.POINTS, 0, 1);
    }

    window.onload = function () {
      getGLContext()
      initShaders()
      setupBuffer()
      draw()
    }
  </script>
</body>

</html>